﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using HA.MT3DMS.FileLayer;

namespace HA.MT3DMS.DomainLayer
{

    [Serializable]
    public class Advection:MTPackage,ICloneable
    {

        public Advection()
        {
            this._solutionScheme = AdvectionSolutionScheme.ThirdOrderTVD;

            this._weightingScheme = AdvecionWeightingScheme.UpstreamWeighting;



            this._trackingAlgorithm = AdvectionTrackingAlgorithm.FirstOrderEuler;
            this._Numberof = NumberofPlances.RandomParticle;
            this._ParticlesCells = NumberofPlances.RandomParticle;
        }




        AdvectionSolutionScheme _solutionScheme;

        public AdvectionSolutionScheme SolutionScheme
        {
            get { return _solutionScheme; }
            set { _solutionScheme = value; }
        }

        AdvecionWeightingScheme _weightingScheme;

        public AdvecionWeightingScheme WeightingScheme
        {
            get { return _weightingScheme; }
            set { _weightingScheme = value; }
        }


        AdvectionTrackingAlgorithm _trackingAlgorithm;

        public AdvectionTrackingAlgorithm TrackingAlgorithm
        {
            get { return _trackingAlgorithm; }
            set { _trackingAlgorithm = value; }
        }

        private NumberofPlances _Numberof;

        public NumberofPlances Numberof
        {
            get { return _Numberof; }
            set { _Numberof = value; }
        }

        private NumberofPlances _ParticlesCells;

        public NumberofPlances ParticlesCells
        {
            get { return _ParticlesCells; }
            set { _ParticlesCells = value; }
        }

      
        private double _PERCEL=1.0;//在一个运移步内任何方向所允许的柯朗数（即单元数或一个单元的分数）对流 
        /// <summary>
        /// 在一个运移步内任何方向所允许的柯朗数（即单元数或一个单元的分数）对流 
        /// </summary>
        public double PERCEL
        {
            get { return _PERCEL; }
            set { _PERCEL = value; }
        }

        private int _MXPART=75000;//被允许的活动颗粒的最大总数，并只有在MIXELM=1或3的时候使用
        /// <summary>
        /// 被允许的活动颗粒的最大总数，并只有在MIXELM=1或3的时候使用
        /// </summary>
        public int MXPART
        {
            get { return _MXPART; }
            set { _MXPART = value; }
        }   

        private double _WD = 0.5;//一个0.5和1之间的浓度权重因子。它用于帮助算子在基于颗粒跟踪的方法上分裂。一个0.5的数值是一般适用的。WD值可以调适以便取得更好的衡。一般来说，当对流越加主导时，它的值可以向1增长。

        /// <summary>
        /// 一个0.5和1之间的浓度权重因子。它用于帮助算子在基于颗粒跟踪的方法上分裂。
        /// 一个0.5的数值是一般适用的。WD值可以调适以便取得更好的衡。
        /// 一般来说，当对流越加主导时，它的值可以向1增长。
        /// </summary>
        public double WD
        {
            set { _WD = value; }
            get { return _WD; }
        }

        private double _DCEPS = 0.00001;//一个小的相对单元浓度梯度，当梯度小于DCEPS值，对流运移可以忽略不计。一个10-5左右的数值是一般适用的。
        /// <summary>
        /// 一个小的相对单元浓度梯度，当梯度小于DCEPS值，对流运移可以忽略不计。
        /// 一个10^-5左右的数值是一般适用的。
        /// </summary>
        public double DCEPS
        {
            get { return _DCEPS; }
            set { _DCEPS = value; }
        }

        private int _NPLANE=2;//一个标示是否以随机或固定模式来选择移动颗粒的初始位置的标识
        /// <summary>
        /// 一个标示是否以随机或固定模式来选择移动颗粒的初始位置的标识
        /// =0，选用随机模式来决定初始位置，此字段设置为0
        /// >0，选用固定模式来决定初始位置
        /// 对于平视的二维模拟，将NPLANE设置为1
        /// 对于横断面或三维模拟，NPLANE=2比较适合
        /// 如果需要竖直方向更多的解，适当提高NPLANE值
        /// </summary>
        public int NPLANE
        {
            get { return _NPLANE; }
            set { _NPLANE = value; }
        }

        private int _NPL;//相对单元浓度梯度小于或等于DCEPS的单元中每单元初始颗粒的数量
        /// <summary>
        /// 相对单元浓度梯度小于或等于DCEPS的单元中每单元初始颗粒的数量
        /// </summary>
        public int NPL
        {
            get { return _NPL; }
            set { _NPL = value; }
        }
        private int _NPH=16;//相对单元浓度大于DCEPS的单元中每单元初始颗粒的数量。NPH的选择取决于流场的特性和电脑内存的限制
        /// <summary>
        /// 相对单元浓度大于DCEPS的单元中每单元初始颗粒的数量。
        /// NPH的选择取决于流场的特性和电脑内存的限制
        /// </summary>
        public int NPH
        {
            get { return _NPH; }
            set { _NPH = value; }
        }
        private int _NPMIN=2;//是每个单元中允许的最小颗粒数
        /// <summary>
        /// 是每个单元中允许的最小颗粒数,一般来说一个在0和4之间的数是适宜的
        /// </summary>
        public int NPMIN
        {
            get { return _NPMIN; }
            set { _NPMIN = value; }
        }
        private int _NPMAX=32;//每个单元中允许的最大颗粒数,一般来说NPMAX可以被设为NPH的两倍
        /// <summary>
        /// 每个单元中允许的最大颗粒数,一般来说NPMAX可以被设为NPH的两倍
        /// </summary>
        public int NPMAX
        {
            get { return _NPMAX; }
            set { _NPMAX = value; }
        }

        private int _INTERP=1;//一个标识，表示在MMOC方案中使用的浓度内插法。现在只有使用线性内插法。输入INTERP=1
        /// <summary>
        /// 一个标识，表示在MMOC方案中使用的浓度内插法。现在只有使用线性内插法。输入INTERP=1,（目前只有默认为1，内部设置）
        /// </summary>
        public int INTERP
        {
            get { return _INTERP; }
            set { _INTERP = value; }
        }
        private int _NLSINK=2;//一个标识，表示颗粒的初始位置是否选用随机或固定模式在MMOC方案中估算源单元。惯例是与NPLANE一样。一般将NLSINK设为与NPLANE一样是适宜的。
        /// <summary>
        /// 一个标识，表示颗粒的初始位置是否选用随机或固定模式在MMOC方案中估算源单元。
        /// 惯例是与NPLANE一样。一般将NLSINK设为与NPLANE一样是适宜的。
        /// </summary>
        public int NLSINK
        {
            get { return _NLSINK; }
            set { _NLSINK = value; }
        }
        private int _NPSINK=16;//在MMOC方案中用来估算源单元的的颗粒数。惯例是与NPH一样。一般将NPSINK设为与NPH一样是适宜的
        /// <summary>
        /// 在MMOC方案中用来估算源单元的的颗粒数。
        /// 惯例是与NPH一样。一般将NPSINK设为与NPH一样是适宜的
        /// 如果是随机选项此字段为0
        /// </summary>
        public int NPSINK
        {
            get { return _NPSINK; }
            set { _NPSINK = value; }
        }
        private double _DCHMOC=0.001;//关键相对浓度坡度用来在HMOC解决方案控制选用MOC或MMOC
        /// <summary>
        /// 关键相对浓度坡度用来在HMOC解决方案控制选用MOC或MMOC
        /// 在相对浓度坡度大于DCHMOC的单元选用MOC解法
        /// 在相对浓度坡度小于或等于DCHMOC的单元选用MMOC解法
        /// </summary>
        public double DCHMOC
        {
            get { return _DCHMOC; }
            set { _DCHMOC = value; }
        }


        public AdvectionPack ToPack()
        {
            AdvectionPack Adv = new AdvectionPack();
            switch (this.SolutionScheme)
            {
                case AdvectionSolutionScheme.ThirdOrderTVD:
                    Adv.MIXELM = -1;
                    break;
                case AdvectionSolutionScheme.MethodOfCharacteristics:
                    Adv.MIXELM = 1;
                    break;
                case AdvectionSolutionScheme.ModifiedMethodOfCharacteristics:
                    Adv.MIXELM = 2;
                    break;
                case   AdvectionSolutionScheme.HbridMOCOrMMOC:
                    Adv.MIXELM = 3;
                    break;
                case AdvectionSolutionScheme.StandardFiniteDifference:
                    Adv.MIXELM = 0;
                    break;
            }
            Adv.PERCEL = this.PERCEL;
            Adv.MXPART = this.MXPART;
            if (this.WeightingScheme == AdvecionWeightingScheme.UpstreamWeighting)
            {
                Adv.NADVFD = 1;
            }
            else
            {
                Adv.NADVFD = 2;
            }

            switch (this.TrackingAlgorithm)
            {
                case AdvectionTrackingAlgorithm.FirstOrderEuler:
                    Adv.ITRACK = 1;
                    break;
                case AdvectionTrackingAlgorithm.FourthOrderRungeKutta:
                    Adv.ITRACK = 2;
                    break;
                case AdvectionTrackingAlgorithm.RungeKuttaAtOrNearSource:
                    Adv.ITRACK = 3;
                    break;
            }
            Adv.WD = this.WD;
            Adv.DCEPS = this.DCEPS;
            if (this.Numberof == NumberofPlances.FixedPattern)
            {
                Adv.NPLANE = this.NPLANE;
            }
            else
            {
                Adv.NPLANE = 0;
            }
            Adv.NPL = this.NPL;
            Adv.NPH = this.NPH;
            Adv.NPMIN = this.NPMIN;
            Adv.NPMAX = this.NPMAX;

            Adv.INTERP = this.INTERP;
            if (this.ParticlesCells == NumberofPlances.FixedPattern)
            {
                Adv.NLSINK = this.NLSINK;
            }
            else
            {
                Adv.NLSINK = 0;
            }
            Adv.NPSINK = this.NPSINK;
            Adv.DCHMOC = this.DCHMOC;


            return Adv ;
        }



        public object Clone()
        {
            return this.MemberwiseClone();
        }
    }
}
